﻿#ifndef IMPORTHPGL_H
#define IMPORTHPGL_H

#include <QObject>
#include <QPen>
#include <QPainter>
#include <QFont>
#include <QFile>
#include <QCoreApplication>
#include <QDir>
#include <QProcess>
#include <QStringList>
#include <QImage>
#include <QBitmap>
#include <qtextcodec.h>
#include "marker.h"
#include "machine/comm/config.h"
#include "machine/comm/datadef.h"
#include "machine/comm/crc16.h"

#define DEFCMD_IN	0x8A //IN
#define DEFCMD_SP	0x7C	//SP
#define DEFCMD_LT	0xE6	//LT 0:PS_SOLID; 1:PS_DASH; 2:PS_DOT; 3:PS_DASHDOT
#define DEFCMD_PG	0x97	//PG
#define DEFCMD_PU	0xB5	//PU 单个PU
#define DEFCMD_PD	0x3D	//PD 单个PD
#define DEFCMD_LPU	0x5E	//PU 连续PU
#define DEFCMD_LPD	0x3B //PD 连续PD
#define DEFCMD_DI	0x5B	//AG 角度
#define DEFCMD_SI	0x5D	//SI 64位双精度浮点
#define DEFCMD_FN	0x4B	//FN 字体名
#define DEFCMD_LB	0x4D	//LB
#define DEFCMD_BT	0x9A	//BIT 位图
#define DEFCMD_CODE	0xE7	//CODE 条形码、二维码
#define DEFCMD_NULL    0x00 //NUll 空指令
#define DEFCMD_DRILL   0xD2 //DRILL 冲孔
#define DEFCMD_NOTCH 0xD3 //NOTCH 剪口

#define M_IDPMM 40.0
#define MMPIXELY    7.936508

#define PREVIEW_SIDE    (10)
#define PREVIEW_WIDTH   (240)
#define PREVIEW_HEIGHT  (240)

#define WIDTHBYTES(bits) (((bits)+31)/32*4)

#define    PixelFormatIndexed      0x00010000 // Indexes into a palette
#define    PixelFormatGDI          0x00020000 // Is a GDI-supported format
#define    PixelFormat1bppIndexed     (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI)

#define PLT_PREVIEW_SIDE    (15)     // 留边大小
#define PLT_PREVIEW_WIDTH   (156)   // 默认预览图区域宽度
#define PLT_PREVIEW_HEIGHT  (164)   // 默认预览图区域高度

#define PLT_EMB_DATADIRX    (1)       // X向数据坐标与下位机坐标系统的差异
#define PLT_EMB_DATADIRY    (1)     // Y向数据坐标与下位机坐标系统的差异      coco 20241205因飞行平板切割机:1. 平板切割机:-1因为机器坐标原点在左上角
#define PLT_EMB_DATADIRR    (1)      // R向数据坐标与下位机坐标系统的差异
#define PLT_EMB_DATASCALE   100   // plt数据转为下位机数据需要扩大10倍，因为下位机单位为0.01mm

#define PLT_SHOWDIRX    (1)     // X向显示坐标和数据坐标的差异
#define PLT_SHOWDIRY    (-1)     // Y向显示坐标和数据坐标的差异               平板切割机:1  飞行平板切割机:-1

struct SC
{
    double dXMin;
    double dXMax;
    double dYMin;
    double dYMax;
    int nType;
    double dLeft;
    double dBottom;
};

class ImportHPGL : public QObject
{
    Q_OBJECT
public:
    explicit ImportHPGL(QObject *parent = 0);
    virtual ~ImportHPGL();

signals:

public slots:

private:
    inline const QString & getFileFullPathName() const {return m_fileFullPathName;}   // 文件路径名称

    //获得QR二维码版本
    //输入参数：nCount 字符个数
    //返回参数：QR二维码版本
    int GetQRVesion(int nCount);

    //样点旋转
    //输入参数:
    //    ptPoint被旋转点,ptPointO旋转原点,dSinBeta,dCosBeta逆时针旋转角度的正余弦
    //输出参数:
    //    ptPoint旋转后的值
    void PointRotate(QPoint &ptPoint,QPoint ptPointO,double dSinBeta,double dCosBeta);

protected:

    //分析S指令
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  bEndOfFile =true 已到文件尾
    //返回值:
    //  true 正确的G指令
    //  false 不正确的G指令
    bool S_Code();
    bool I_Code();
    bool P_Code();
    bool PU_Code();
    bool PD_Code();
    bool L_Code();
    bool D_Code();
    bool SC_Code();
    bool C_Code();

    //读取一个字符
    //输出参数:
    //  *pChar  读取的字符
    //返回值:
    //  1 成功取得一个字符
    //  0 失败
    uint ReadChar(char* lpBuf);

    //读取一个非空格、非回车、非换行的字符
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  *pChar  读取的字符
    //返回值:
    //  true 成功取得一个字符
    //  false 失败
    bool GetChar(char *pChar);
    //判断下一个非空格、非回车、非换行的字符是不是','
    //输入参数:
    //  pFile 切割数据文件
    //返回值:
    //  true 下一个非空格、非回车、非换行的字符是',', 并且已将','从文件中读出
    //  false 下一个非空格、非回车、非换行的字符不是',', 并且该字符没有从文件中读出
    bool NextCharIsComma();

    //取一个双精度浮点数
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  dValue  取得的双精度浮点数
    //返回值:
    //  true 成功取得一个双精度浮点数dValue
    //  false 失败
    bool GetDoubleData(double &dValue);

    //取一个整数
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  iValue  取得的整数
    //返回值:
    //  true 成功取得一个整数iValue
    //  false 失败
    bool GetIntegerData(int &iValue);

    //取坐标值
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  ptPoint  坐标
    //返回值:
    //  true 成功
    //  false 失败
    bool GetCoordinate(QPoint &ptPoint);

    //获得线的类型
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  lineType  线型
    //返回值:
    //  true 成功
    //  false 失败
    bool GetLineType(LineType &lineType);

    //查找一个指定的字符
    //输入参数:
    //  pFile 切割数据文件
    //  cFind 指定的字符
    //输出参数:
    //  strInfo 从开始位置到指定字符之前的内容(不包括最后的指定字符)
    //返回值:
    //  true 成功取得一个字符
    //  false 失败
    bool SearchChar(char cFind,QString &strInfo);

    //将文件的读取位置移到下一个英文字母(26个英文字母)
    //输入参数:
    //  pFile 切割数据文件
    //输出参数:
    //  *pChar  读取的字符
    //返回值:
    //  true 成功将文件的读取位置移到下一个英文字母
    //  false 失败
    bool MoveToNextEnglishChar();

    //将m_listXY加入到m_pMarker中,并将m_listXY清空
    void AddPolylineToMarker();

    void AddPoint2listXY(QPoint ptPoint);

    QString m_fileFullPathName; //文件名称
    int m_iDPMM;  //长度数据单位:m_iDPMM(每毫米点)
    int m_iPenNo;  //当前的笔号
    QPoint m_ptCurrentPos;  //笔的当前位置,单位:(1/CMarker::m_iDPMM)毫米
    LineType m_lineType;//当前线型
    bool m_bPenUp;//当前刀具的状态 true:刀具状态为抬起  false：刀具状态为落下
    bool m_bPage;//是否识别到PG指令

    Marker *m_pMarker;  //当前使用的唛架,仅能在读文件时使用
    double m_dScale;  //读入文件时将切割数据文件的单位转换成内部数据单位时的比例
    QPen m_penPen;//笔绘画笔
    QPen m_cutPen;//切割画笔
    QPen m_halfCutPen;//半透切割画笔

    QList <QPoint>  m_listXY;  //还没有确定抬落刀的坐标
    //QPainterPath m_polylinePainterPath;//绘图路径-线段

    unsigned char m_chTerminator;//标志终结符,除了NULL LF ESC及;十进制分别为0,5,27,59;外的所有字符，默认为ETX 十进制3
    int m_nTerminatorMode;//模式0：打印1：不打印 默认值为1

    double m_dTextHeight;//字的高度 单位cm
    double m_dTextWidth;//字的宽度 单位cm
    int m_nLableOrigin;//字符串相对于原点位置
    double m_dTextAngle;//指定每行文本输出时相对于设备x轴的角度，其单位为1/10度
    QPoint m_ptP1;//解析IP指令中的坐标点
    QPoint m_ptP2;//解析IP指令中的坐标点
    SC m_sc;//解析SC指令
    double m_dScaleX;//通过 IP和SC指令算出的缩放比例
    double m_dScaleY;//通过 IP和SC指令算出的缩放比例
    QPoint m_ptOrigin;//通过 IP和SC指令算出的原点
    int m_nLength;//用于PG分页，记录累计长度
    char* m_pFileBuf;//存放从文件中读取的全部字符
    int m_nCharCount;//已经读取的字符个数
    int m_nFileLength;//文件长度
    QString m_workPath;

    bool m_bFontItalic;  //文字斜体
    int m_iFontSize; //字体榜数
    QString m_strFontName;//字体名称

private:
    QByteArray m_embAbsData;    // 转换后的绝对坐标数据
    int m_minX;
    int m_maxX;
    int m_minY;
    int m_maxY;
    u8 m_stepCtrl;

public:
    //输入参数:
    //  pFile 需要读入的RS274D文件
    //  pMarker 解析到的数据保存到此唛架
    //返回值:
    //  true 读入文件成功
    //  false 读入文件失败
    bool Read(QString strPathName);
    bool Write(QString strPathName,Marker *pMarker);
    int createPreviewImage(QImage * pImg = NULL, int saveflag = 0, int penwidth = 1, int reDraw = 0);  // 生成预览文件
    void convertDataToEmbAbs();     // 转换为绝对数据
    void setStepCtrl(u8 ctrl);//设置针步属性
    QByteArray getEmbAbsData();          // 得到转换后的数据

    //void creatPolylinePainterPath();//获得文件图形的范围
    //QPainterPath GetPolylinePainterPath();

    //初始化参数，读取参数前，需将参数值重置，避免造成参数值读取错误
    void IniPara();

    QPoint GetTextOrigin(QPoint pt,QString strText);
    double GetTextAngle(double dX,double dY);
    void SetScale();    
    bool IsSecretFile(QString strPatnName);
    int BitMapDtat(QString strFileName,QString strSecretFile);
    bool ReadSecretFile(QString stePathName);  // 打开位图文件

private slots:
    //输入参数:
    //  bUp 刀的状态，true：抬起状态 false：落下状态
    //  ptPoint 矢量字体中点阵中的一个坐标
    void AddTextPointToLine(bool bUp,QPoint ptPoint);
};

#endif // IMPORTHPGL_H
